﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Ongoal.Quotation.Model;
using Ongoal.Quotation.Redis;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

namespace Ongoal.Quotation
{
    /// <summary>
    /// 
    /// </summary>
    public class APIAuthorizationHandler : AuthorizationHandler<IAuthorizationRequirement>
    {
        private readonly JwtConfig jwtConfig;
        public IConfiguration _config;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="jwtconf"></param>
        /// <param name="config"></param>
        public APIAuthorizationHandler(JwtConfig jwtconf, IConfiguration config)
        {
            jwtConfig = jwtconf;
            _config = config;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="requirement"></param>
        /// <returns></returns>
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IAuthorizationRequirement requirement)
        {
            //检查是否是开发环境，如果是开发环境，直接返回成功
            if (_config["ASPNETCORE_ENVIRONMENT"] == "Development")
            {
                var devCfg = _config.GetCfgValue<DevSetting>("DevSetting");
                if (devCfg != null)
                {
                    List<Claim> claims = new List<Claim>();
                    claims.Add(new Claim("loginuser", Des.Encrypt(JsonConvert.SerializeObject(devCfg.User))));

                    ClaimsIdentity identity = new ClaimsIdentity(claims);
                    ClaimsPrincipal principal = new ClaimsPrincipal(identity);
                    ServiceProviderContext.HttpContextAccessor.HttpContext.User = principal;

                    if (ServiceProviderContext.HttpContextAccessor.HttpContext.Request.Headers.Keys.Contains("ContentUser"))
                    {
                        ServiceProviderContext.HttpContextAccessor.HttpContext.Request.Headers.Remove("ContentUser");
                    }
                    ServiceProviderContext.HttpContextAccessor.HttpContext.Request.Headers.Add("ContentUser", JsonConvert.SerializeObject(devCfg.User));                    
                    context.Succeed(requirement);
                }
                return Task.CompletedTask;
            }

            var _jwt = ServiceProviderContext.ServiceProvider.GetService(typeof(IAuthentication)) as IAuthentication;
            //Headers既不存在Authorization也不存在Token则直接返回未授权
            if (!ServiceProviderContext.HttpContextAccessor.HttpContext.Request.Headers.Keys.Contains("Authorization") && !ServiceProviderContext.HttpContextAccessor.HttpContext.Request.Headers.Keys.Contains(jwtConfig.HeadField))
                return Task.CompletedTask;

            //拿到Token
            string tokenStr = ServiceProviderContext.HttpContextAccessor.HttpContext.Request.Headers.Keys.Contains("Authorization") ? ServiceProviderContext.HttpContextAccessor.HttpContext.Request.Headers["Authorization"].ToString(): ServiceProviderContext.HttpContextAccessor.HttpContext.Request.Headers[jwtConfig.HeadField].ToString();
            
            if (jwtConfig != null && jwtConfig.IgnoreUrls != null && jwtConfig.IgnoreUrls.Contains(ServiceProviderContext.HttpContextAccessor.HttpContext.Request.Path))
            {
                context.Succeed(requirement);
            }
            if (tokenStr.StartsWith("Bearer "))
            {
                tokenStr = tokenStr.Substring(7);
            }
            if (tokenStr.StartsWith("Jwt"))
            {
                tokenStr = tokenStr.Substring(3);
            }

            if (jwtConfig != null)
            {
                List<Claim> claims = new List<Claim>();
                if (_jwt.ValidateToken(tokenStr, out claims))
                {
                    if (claims.Count(x => x.Type == "tokenType" && x.Value == "relashToken") > 0 && (((Microsoft.AspNetCore.Http.DefaultHttpContext)((Microsoft.AspNetCore.Mvc.ActionContext)context.Resource).HttpContext).Request).Path.Value != "/Auth/Login/RlashToken")
                    {
                        context.Fail();
                        return Task.CompletedTask;
                    }
                    ClaimsIdentity identity = new ClaimsIdentity(claims);
                    ClaimsPrincipal principal = new ClaimsPrincipal(identity);
                    ServiceProviderContext.HttpContextAccessor.HttpContext.User = principal;
                    context.Succeed(requirement);
                }
            }
            return Task.CompletedTask;
        }

    }
}
